package csm.common.thread;

/**
 * <b>동일한 주기동안 반복적인 작업</b>을 수행하도록 하는 클래스입니다.
 * <p>
 * Task 클래스를 이용해 주기적인 반복적업을 하고 싶을 경우 다음과 같이 작업할 클래스를 {@link Runnable} 인터페이스를 상속받아, run()메소드를 구현해주면 된다.
 * </p>
 *
 * <pre>
 * class Worker implements Runnable
 * {
 *     public void run()
 *     {
 *         // 작업할 내용.
 *     }
 * }
 * </pre>
 *
 * 이제 구현한 작업 클래스를 다음과 같은 방법으로 Task클래와 연동하여 실행할 수 있다.
 *
 * <pre>
 * Worker worker = new Worker();
 * Task task = new Task(worker, 1000); // 1초간격으로 worker의 작업을 실행.
 * </pre>
 *
 * 또는, 다음과 같이 Worker 클래스 내부에서 Task클래스를 이용하여 실행 할 수 도 있다.
 *
 * <pre>
 * Task task = new Task(this, 1000);
 * </pre>
 *
 * 그 밖에 다른 방법으로는 Task클래스 자체를 상속받아 실행하는 방법이다. 즉, Task클래스를 상속받은 Worker클래스를 작성한다.
 *
 * <pre>
 * class Worker extends Task
 * {
 *     public void run()
 *     {
 *         // 작업할 내용.
 *     }
 * }
 * </pre>
 *
 * 이제, 다음과 같은 구문으로 위에서 언급한 실행효과와 동일한 실행을 할 수 있다.
 *
 * <pre>
 * Task task = new Task(1000);
 * </pre>
 *
 * @author seungmun
 * @since 2006.1.18.
 * @see {@link TaskRunner}
 * @see {@link TaskTimer}
 */
public class Task implements Runnable
{
    protected Runnable   runnable;
    protected long       msPeriod;
    protected TaskRunner runner;
    protected long       nextRun;

    /**
     * 생성자, 이 생성자는 이 클래스를 상속받을때 사용된다.
     *
     * @param msPeriod
     *            실행주기 (milisecond)
     */
    public Task(long msPeriod)
    {
        this(null, msPeriod);
    }

    /**
     * 생성자
     *
     * @param runnable
     *            실행시킬 객체
     * @param msPeriod
     *            실행주기 (milisecond)
     */
    public Task(Runnable runnable, long msPeriod)
    {
        this.runnable = runnable;
        this.msPeriod = msPeriod;
        runner = new TaskRunner(this);
        TaskTimer.add(this);
    }

    /**
     * 작업객체를 실행시키거나, 작업을 시작한다.
     */
    @Override
    public void run()
    {
        if (runnable == null)
            throw new RuntimeException();
        runnable.run();
    }

    /**
     * 현재 작업의 스케줄을 제거한다.
     */
    public synchronized void deschedule()
    {
        TaskTimer.deschedule(this);
    }

    @SuppressWarnings("unused")
    public static void main(String[] args)
    {
        System.out.println("begin of main");

        Worker w1 = new Worker("w1");
        Worker w2 = new Worker("w2");

        Runnable w3 = new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println("Hello");
            }
        };
        Task t1 = new Task(w1, 1000);
        Task t2 = new Task(w2, 3000);
        Task t3 = new Task(w3, 5000);

        System.out.println("end of main");
    }

} // end of class

class Worker implements Runnable
{
    String name = "";

    public Worker(String n)
    {
        name = n;
    }

    public void run()
    {
        System.out.println(name);
    }

}
